home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 418_02 / rasmol2 / raswin.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-03-02  |  58.9 KB  |  1,870 lines

  1. /* raswin.c
  2.  * RasWin Molecular Graphics
  3.  * Roger Sayle, February 1994
  4.  * Version 2.3
  5.  */
  6.  
  7. #include <windows.h>
  8. #include <commdlg.h>
  9. #include <dde.h>
  10.  
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <malloc.h>
  14. #include <stdio.h>
  15. #include <math.h>
  16.  
  17. #define RASMOL
  18. #include "rasmol.h"
  19. #include "raswin.idm"
  20. #include "molecule.h"
  21. #include "graphics.h"
  22. #include "pixutils.h"
  23. #include "transfor.h"
  24. #include "command.h"
  25. #include "abstree.h"
  26. #include "render.h"
  27. #include "outfile.h"
  28.  
  29.  
  30. /* Determine Mouse Sensitivity! */
  31. #define IsClose(u,v) (((u)>=(v)-1) && ((u)<=(v)+1))
  32.  
  33. #define DefaultTimeOut 10000
  34. #define MaxAdviseNum   32
  35. #define MaxConvNum     8
  36.  
  37. #define ColdLink       0x01
  38. #define WarmLink       0x02
  39. #define HotLink        0x03
  40. #define AckLink        0x04
  41.  
  42.  
  43. typedef struct {
  44.         HWND  server;
  45.         HWND  client;
  46.         Byte  closed;
  47.         } DDEConv;
  48.         
  49. typedef struct {
  50.             HANDLE data;
  51.         HWND  server;
  52.         HWND  client;
  53.             ATOM  atom;
  54.             Byte  mode;
  55.             Byte  item;
  56.             Byte  wait;
  57.        } DDEAdvise;
  58.  
  59. static int DDETimeOut;
  60. static DDEAdvise AdviseData[MaxAdviseNum];
  61. static DDEConv ConvData[MaxConvNum];
  62. static int RasWinReady;
  63. static int AdviseCount;
  64. static int ConvCount;
  65.  
  66.  
  67. static char *ItemName[ItemCount] = {
  68.         "Pick",      /* AdvPickAtom    */
  69.         "PickNo",    /* AdvPickNumber  */
  70.         "Count",     /* AdvSelectCount */
  71.         "Name",      /* AdvName        */
  72.         "Ident",     /* AdvIdent       */
  73.         "Class"      /* AdvClass       */
  74.     };
  75.  
  76.  
  77. #define TermSize   (TermRows*TermCols)
  78. #define TermRows   24
  79. #define TermCols   80
  80.  
  81.  
  82. static int TermCursor;
  83. static int CharWide,CharHigh;
  84. static int TermXPos,TermYPos;
  85. static char __far *TermScreen;
  86. static HFONT TermFont;
  87. static HWND CmndWin;
  88.  
  89. static int PointX,PointY;
  90. static int InitX,InitY;
  91. static int HeldButton;
  92. static int MouseMode;
  93.  
  94. static char fnamebuf[128];
  95. static char ofilters[256];
  96. static char ifilters[256];
  97. static OPENFILENAME ofn1;
  98. static OPENFILENAME ofn2;
  99. static HANDLE hInstance;
  100. static int InstanceNo;
  101. static char Text[256];
  102.  
  103.  
  104. long FAR PASCAL MainCallB(HWND, UINT, WPARAM, LPARAM);
  105. long FAR PASCAL CmndCallB(HWND, UINT, WPARAM, LPARAM);
  106. long FAR PASCAL DDECallB( HWND, UINT, WPARAM, LPARAM); 
  107. BOOL FAR PASCAL AboutCallB(HWND, unsigned, WORD, LONG);
  108. BOOL FAR PASCAL InfoCallB(HWND, unsigned, WORD, LONG);
  109.  
  110.  
  111.  
  112. static void CloseDDELinks()
  113. {
  114.     register long alarm;
  115.     register int i;
  116.     MSG message;
  117.     
  118.     for( i=0; i<MaxConvNum; i++ )
  119.         if( ConvData[i].server )
  120.         {   ConvData[i].closed = True;
  121.             PostMessage( ConvData[i].client, WM_DDE_TERMINATE,
  122.                          ConvData[i].server, 0L );
  123.         } 
  124.    
  125.     alarm = GetTickCount() + DDETimeOut;
  126.     while( PeekMessage(&message,NULL,WM_DDE_FIRST,WM_DDE_LAST,PM_REMOVE) )
  127.     {   DispatchMessage( &message );
  128.         if( message.message == WM_DDE_TERMINATE )
  129.             if( !ConvCount ) break;
  130.             
  131.         /* Terminate Time Out */
  132.         if( (long)GetTickCount() > alarm )
  133.         {   for( i=0; i<MaxConvNum; i++ )
  134.                 if( ConvData[i].server )
  135.                     DestroyWindow( ConvData[i].server );
  136.             break;
  137.         }
  138.     }
  139. }
  140.  
  141.  
  142. void RasMolExit()
  143. {
  144.     DeleteObject(TermFont);
  145.     CloseDDELinks();
  146.     CloseDisplay();
  147.     exit(0);
  148. }
  149.  
  150.  
  151. void RasMolFatalExit( msg )
  152.     char *msg;
  153. {
  154.     MessageBox(NULL,msg,"RasMol Fatal Error!",
  155.         MB_OK | MB_ICONEXCLAMATION | MB_APPLMODAL );
  156.     
  157.     /* PostQuitMessage(0); */
  158.     DeleteObject(TermFont);
  159.     CloseDDELinks();
  160.     CloseDisplay();
  161.     exit(1);    
  162. }
  163.  
  164.  
  165. static void LoadInitFile()
  166. {
  167.     register char *src,*dst;
  168.     register FILE *initrc;
  169.     register char *fname;
  170.  
  171.     fname = "RASMOL.INI";
  172.     initrc = fopen(fname,"r");
  173.     if( !initrc && (src=(char*)getenv("HOME")) )
  174.     {   dst = fnamebuf; 
  175.         while( *src )
  176.             *dst++ = *src++;
  177.         *dst++ = '\\';
  178.  
  179.         src = fname; fname = fnamebuf;
  180.         while( *dst++ = *src++ );
  181.         initrc = fopen(fname,"r");
  182.     }
  183.  
  184.     if( initrc )
  185.         LoadScriptFile(initrc,fname);
  186. }
  187.  
  188.  
  189.  
  190. void WriteChar( ch )
  191.     char ch;
  192. {
  193.     RECT rect;
  194.     
  195.     switch( ch )
  196.     {    case(0x07):  MessageBeep(0);
  197.                       break;
  198.                       
  199.          case(0x08):  if( TermXPos>0 )
  200.                       {   TermXPos--;
  201.                           if( TermCursor )
  202.                               SetCaretPos(TermXPos*CharWide,
  203.                                           TermYPos*CharHigh);
  204.                       }
  205.                   break;
  206.                   
  207.          case(0x0D):  if( TermXPos )
  208.                       {   if( TermCursor )
  209.                               SetCaretPos(0,TermYPos*CharHigh);
  210.                           TermXPos=0;
  211.                       }
  212.                       break;
  213.                       
  214.          case(0x0A):  if( TermYPos==TermRows-1 )
  215.                       {   _fmemmove(TermScreen,TermScreen+TermCols,
  216.                                     TermSize-TermCols);
  217.                           _fmemset(TermScreen+TermSize-TermCols,' ',TermCols);
  218.                           InvalidateRect(CmndWin,NULL,FALSE);
  219.                       } else TermYPos++;
  220.                       TermXPos = 0;
  221.  
  222.                       if( TermCursor )
  223.                           SetCaretPos(0,TermYPos*CharHigh);
  224.                       UpdateWindow(CmndWin);
  225.                       break;
  226.                       
  227.          
  228.          default:     TermScreen[TermYPos*TermCols+TermXPos]=ch;
  229.                       rect.top = TermYPos*CharHigh; 
  230.                       rect.left = TermXPos*CharWide;
  231.                       rect.bottom = rect.top+CharHigh;
  232.                       rect.right = rect.left+CharWide;
  233.                       InvalidateRect(CmndWin,&rect,FALSE);
  234.                       
  235.                       if( TermXPos==TermCols-1 )
  236.                       {   if( TermYPos==TermRows-1 )
  237.                           {   _fmemmove(TermScreen,TermScreen+TermCols,
  238.                                         TermSize-TermCols);
  239.                               _fmemset(TermScreen+TermSize-TermCols,
  240.                                        ' ',TermCols);
  241.                               InvalidateRect(CmndWin,NULL,FALSE);
  242.                           } else TermYPos++;
  243.                             TermXPos=0;
  244.                       } else TermXPos++;
  245.  
  246.                       if( TermCursor )
  247.                           SetCaretPos(0,TermYPos*CharHigh);
  248.                       break;
  249.                       
  250.     }
  251. }
  252.  
  253.  
  254. void WriteString( ptr )
  255.     char *ptr;
  256. {
  257.     while( *ptr )
  258.         WriteChar(*ptr++);
  259. }
  260.  
  261.  
  262. static int InitTerminal( instance )
  263.     HANDLE instance;
  264. {
  265.     TEXTMETRIC Text;
  266.     LOGFONT LogFont;
  267.     long style;
  268.     RECT rect;
  269.     HDC hDC;
  270.  
  271.     
  272.     LogFont.lfHeight     = 12;
  273.     LogFont.lfWidth      = 0;
  274.     LogFont.lfEscapement = 0;
  275.     LogFont.lfWeight     = 0;
  276.     LogFont.lfItalic     = 0;
  277.     LogFont.lfUnderline  = 0;
  278.     LogFont.lfStrikeOut  = 0;
  279.     
  280.     LogFont.lfCharSet        = OEM_CHARSET;
  281.     LogFont.lfOutPrecision   = OUT_DEFAULT_PRECIS;
  282.     LogFont.lfClipPrecision  = CLIP_DEFAULT_PRECIS;
  283.     LogFont.lfQuality        = DEFAULT_QUALITY;
  284.     LogFont.lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
  285.     LogFont.lfFaceName[0]    = NULL;
  286.     TermFont = CreateFontIndirect(&LogFont);
  287.  
  288.     TermXPos = TermYPos = 0;
  289.     TermScreen = (char __far*)_fmalloc(TermSize*sizeof(char));
  290.     if( !TermScreen ) return( False );
  291.     _fmemset(TermScreen,' ',TermSize);
  292.     TermCursor = False;
  293.  
  294.  
  295.     hDC = GetDC(NULL);
  296.     SelectObject(hDC,TermFont);
  297.     GetTextMetrics(hDC,&Text);  
  298.     ReleaseDC(NULL,hDC);
  299.     
  300.     CharWide = Text.tmAveCharWidth;
  301.     CharHigh = Text.tmHeight + Text.tmExternalLeading;
  302.  
  303.     rect.top  = 0;   rect.bottom = TermRows*CharHigh;
  304.     rect.left = 0;   rect.right  = TermCols*CharWide;
  305.     
  306.     style = WS_OVERLAPPED | WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX;
  307.     
  308.     AdjustWindowRect(&rect,style,TRUE);
  309.     CmndWin = CreateWindow("RasCliClass", "RasMol Command Line",
  310.                            style, CW_USEDEFAULT, CW_USEDEFAULT,
  311.                            rect.right-rect.left, rect.bottom-rect.top,
  312.                            NULL, NULL, instance, NULL );
  313.                            
  314.     if( !CmndWin ) return( False );
  315.     ShowWindow(CmndWin,SW_SHOWMINNOACTIVE);
  316.     return( True );
  317. }
  318.  
  319.  
  320.  
  321. static void PaintScreen()
  322. {
  323.     int SRow,ERow,SCol,ECol;
  324.     register char __far *ptr;
  325.     register int row,len;
  326.     register int x,y;
  327.     
  328.     PAINTSTRUCT ps;
  329.     HFONT font;
  330.     RECT rect;
  331.     HDC hDC;
  332.     
  333.     hDC = BeginPaint(CmndWin,&ps);
  334.     font = SelectObject(hDC,TermFont);
  335.     SetBkColor(hDC,GetSysColor(COLOR_WINDOW));
  336.     SetTextColor(hDC,RGB(0,0,0));
  337.     SetBkMode(hDC,OPAQUE);
  338.     
  339.     SRow = ps.rcPaint.top/CharHigh;
  340.     if( SRow>=TermRows ) SRow=TermRows-1; 
  341.     else if( SRow<0 ) SRow=0;
  342.     
  343.     ERow = ps.rcPaint.bottom/CharHigh;
  344.     if( ERow>=TermRows ) ERow=TermRows-1;
  345.     else if( ERow<0 ) ERow=0;
  346.     
  347.     SCol = ps.rcPaint.left/CharWide;
  348.     if( SCol>=TermCols ) SCol=TermCols-1;
  349.     else if( SCol<0 ) SCol=0;
  350.     
  351.     ECol = ps.rcPaint.right/CharWide;
  352.     if( ECol>=TermCols ) ECol=TermCols-1;
  353.     else if( ECol<0 ) ECol=0;
  354.  
  355.     len = ECol-SCol+1;
  356.     x = SCol*CharWide;
  357.     y = SRow*CharHigh;
  358.     ptr = TermScreen + TermCols*SRow + SCol;
  359.     rect.right = x+len*CharWide;
  360.     rect.left = x;   
  361.    
  362.     for( row=SRow; row<=ERow; row++ )
  363.     {   rect.top = y;    
  364.         rect.bottom = y+CharHigh;
  365.         ExtTextOut(hDC,x,y,ETO_OPAQUE|ETO_CLIPPED,
  366.                    &rect,ptr,len,NULL);        
  367.         ptr += TermCols;
  368.         y += CharHigh;
  369.     }
  370.     
  371.     SelectObject(hDC,font);
  372.     EndPaint(CmndWin,&ps);
  373.     
  374.     if( TermCursor )
  375.         SetCaretPos(TermXPos*CharWide,TermYPos*CharHigh);
  376. }
  377.  
  378.  
  379.  
  380. BOOL FAR PASCAL AboutCallB(hWin,uMsg,wArg,lArg)
  381.     HWND hWin; unsigned uMsg; WORD wArg; LONG lArg;
  382. {
  383.     register DWORD flags;
  384.     register int len; 
  385.    
  386.     switch(uMsg)
  387.     {   case(WM_INITDIALOG):  flags = GetWinFlags();
  388.                               if( flags & WF_CPU286 )
  389.                               {      len = sprintf(Text,"286 with");
  390.                               } else if( flags & WF_CPU386 )
  391.                               {      len = sprintf(Text,"386 with");
  392.                               } else len = sprintf(Text,"486 with");
  393.                               
  394.                               if( !(flags&WF_80x87) )
  395.                               {   sprintf(Text+len,"out maths coprocessor");
  396.                               } else sprintf(Text+len," maths coprocessor"); 
  397.                               SetDlgItemText(hWin,IDD_HARDWARE,Text);         
  398.                               return(TRUE);
  399.     
  400.         case(WM_COMMAND):     if( wArg == IDOK )
  401.                               {   EndDialog(hWin,TRUE);
  402.                                   return(TRUE);
  403.                               }
  404.                               break;
  405.     }
  406.     return(FALSE);
  407. }
  408.  
  409.  
  410. static void DisplayMoleculeInfo( hWin )
  411.     HWND hWin;
  412. {
  413.     register int line;
  414.     register int len;
  415.  
  416.     line = IDD_INFOTEXT;
  417.     
  418.     if( *InfoMoleculeName )
  419.     {   sprintf(Text,"Molecule name ...... %s",InfoMoleculeName);
  420.         SetDlgItemText(hWin,line++,Text);
  421.     }
  422.     
  423.     if( *InfoClassification )
  424.     {   sprintf(Text,"Classification ......... %s",InfoClassification);
  425.         SetDlgItemText(hWin,line++,Text);
  426.     }
  427.     
  428.     if( *InfoIdentCode )
  429.     {   sprintf(Text,"Brookhaven code .. %s",InfoIdentCode);
  430.         SetDlgItemText(hWin,line++,Text);
  431.     }
  432.     
  433.     if( InfoChainCount>1 )
  434.     {   sprintf(Text,"Number of chains .. %d",InfoChainCount);
  435.         SetDlgItemText(hWin,line++,Text);
  436.     }
  437.     
  438.     len = sprintf(Text,"Number of groups .. %d",MainGroupCount);
  439.     if( HetaGroupCount ) sprintf(Text+len," (%d)",HetaGroupCount);
  440.     SetDlgItemText(hWin,line++,Text);
  441.  
  442.     len = sprintf(Text,"Number of atoms ... %ld",MainAtomCount);
  443.     if( HetaAtomCount ) sprintf(Text+len," (%d)",HetaAtomCount);
  444.     SetDlgItemText(hWin,line++,Text);
  445.  
  446.  
  447.     sprintf(Text,"Number of bonds ... %ld",InfoBondCount);
  448.     SetDlgItemText(hWin,line++,Text);
  449. }
  450.  
  451.         
  452. BOOL FAR PASCAL InfoCallB(hWin,uMsg,wArg,lArg)
  453.     HWND hWin; unsigned uMsg; WORD wArg; LONG lArg;
  454. {
  455.     switch(uMsg)
  456.     {   case(WM_INITDIALOG):  DisplayMoleculeInfo(hWin);
  457.                               return(TRUE);
  458.                               
  459.         case(WM_COMMAND):     if( wArg == IDOK )
  460.                               {   EndDialog(hWin,TRUE);
  461.                                   return(TRUE);
  462.                               }
  463.                               break;
  464.     }
  465.     return(FALSE);
  466. }
  467.  
  468.  
  469. static char *GetItemName( item )
  470.     int item;
  471. {
  472.     switch( item )
  473.     {   case(-1):  return("Topics");
  474.         case(-2):  return("SysItems");
  475.         case(-3):  return("Formats");
  476.         case(-4):  return("Status");
  477.         case(-5):  return("Items");
  478.     }
  479.  
  480.     if( item<=ItemCount )
  481.         return( ItemName[item-1] );
  482.     return( "" );
  483. }
  484.  
  485.  
  486. static void SendItemData( hSrc, hDst, mode, item, advise )
  487.     HWND hSrc, hDst;  int mode, item, advise;
  488. {
  489.     DDEDATA FAR *data;
  490.     HANDLE hData;
  491.     ATOM atom;
  492.  
  493.     register char __far *dest;
  494.     register char *src,*dst;
  495.     register char *name;
  496.     register int i,len;
  497.  
  498.     name = GetItemName(item);
  499.  
  500.     if( mode==WarmLink )
  501.     {   atom = GlobalAddAtom(name);
  502.         if( !PostMessage(hDst,WM_DDE_DATA,hSrc,MAKELONG(0,atom)) )
  503.             GlobalDeleteAtom(atom);
  504.         return;
  505.     }
  506.  
  507.     dst = Text;
  508.     if( item>0 )
  509.         item--;
  510.         
  511.     switch( item )
  512.     {   case(-1): /* Topics */
  513.                   src="System\tRemoteControl"; 
  514.                   while( *dst++ = *src++ ); break;
  515.  
  516.         case(-2): /* SysItems */
  517.                   src = "Topics\tSysItems\tFormats\tStatus\tItems";
  518.                   while( *dst++ = *src++ ); break;
  519.  
  520.         case(-3): /* Formats */
  521.                   src = "DIB\tTEXT\tPalette\tLink";
  522.                   while( *dst++ = *src++ ); break;
  523.  
  524.         case(-4): /* Status */
  525.                   src = RasWinReady? "Ready" : "Busy";
  526.                   while( *dst++ = *src++ ); break;
  527.  
  528.         case(-5): /* Items */
  529.                   for( i=0; i<ItemCount; i++ )
  530.                   {   if( i ) *dst++ = '\t';
  531.                       src = GetItemName(i); 
  532.                       while( *src )
  533.                           *dst++ = *src++;
  534.                   }
  535.                   *dst = '\0';
  536.                   break;
  537.  
  538.         case(AdvPickAtom):
  539.                   if( QAtom )
  540.                   {   src = Residue[QGroup->refno];
  541.                       if( src[0]!=' ' ) *dst++ = src[0];
  542.                       *dst++  = src[1]; *dst++ = src[2];
  543.  
  544.                       sprintf(dst,"%d",QGroup->serno);
  545.                       for( dst=Text; *dst; dst++ );
  546.                       if( QChain->ident!=' ' )
  547.                       {   *dst++ = ':';
  548.                           *dst++ = QChain->ident;
  549.                       }
  550.                       *dst++ = '.';
  551.                       
  552.                       src = ElemDesc[QAtom->refno];
  553.                       if( src[0]!=' ' ) *dst++ = src[0];
  554.                       *dst++  = src[1]; *dst++ = src[2];
  555.                       if( src[3]!=' ' ) *dst++ = src[3];
  556.                   } 
  557.                   *dst = '\0';
  558.                   break;
  559.  
  560.         case(AdvPickNumber):
  561.                   if( QAtom )
  562.                   { sprintf(dst,"%d",QAtom->serno);
  563.                   } else *dst = '\0';
  564.                   break;
  565.  
  566.         default:  *dst = '\0';
  567.                   break;
  568.     }
  569.  
  570.     len = sizeof(DDEDATA);
  571.     for( dst=Text; *dst; dst++ )
  572.         len++;
  573.  
  574.     if( hData = GlobalAlloc(GHND|GMEM_DDESHARE,len) )
  575.     {   if( data = (DDEDATA FAR*)GlobalLock(hData) )
  576.         {   dest = (char __far*)&data->Value[0];
  577.             for( src=Text; *src; *dest++ = *src++ );
  578.             /* Correctly terminate the data string */
  579.             /* *dest++ = '\r'; *dest++ = '\n';     */
  580.             *dest = '\0';
  581.  
  582.             data->cfFormat = CF_TEXT;
  583.             data->fResponse = (mode!=AckLink);
  584.             data->fAckReq = (mode==ColdLink);
  585.             data->fRelease = True;
  586.             
  587.             GlobalUnlock(hData);
  588.             atom = GlobalAddAtom(name);
  589.             if( PostMessage(hDst,WM_DDE_DATA,hSrc,MAKELONG(hData,atom)) )
  590.             {   if( mode==AckLink )
  591.                 {   SetTimer( hSrc, hDst, DDETimeOut, NULL );
  592.                     AdviseData[advise].data = hData;
  593.                     AdviseData[advise].atom = atom;
  594.                     AdviseData[advise].wait = True;
  595.                 }
  596.                 return;
  597.             }
  598.             GlobalDeleteAtom(atom);
  599.         }
  600.         GlobalFree( hData );
  601.     }
  602.     return;
  603. }
  604.  
  605.  
  606. static int GetItemNumber( atom )
  607.     ATOM atom;
  608. {
  609.     register int i;
  610.  
  611.     GlobalGetAtomName(atom,Text,240);
  612.  
  613.     for( i=1; i<6; i++ )
  614.         if( !_stricmp(Text,GetItemName(-i)) )
  615.             return( -i );
  616.  
  617.     for( i=0; i<ItemCount; i++ )
  618.         if( !_stricmp(Text,ItemName[i]) )
  619.             return( i+1 );
  620.     return( 0 );
  621. }
  622.  
  623. void AdviseUpdate( item )
  624.     int item;
  625. {
  626.     register DDEAdvise *ptr;
  627.     register int i;
  628.  
  629.     if( AdviseCount )
  630.         for( i=0; i<MaxAdviseNum; i++ )
  631.         {   ptr = AdviseData + i;
  632.             if( ptr->server && (ptr->item==(Byte)item) )
  633.                 SendItemData(ptr->server,ptr->client,ptr->mode,item,i);
  634.         }
  635. }
  636.  
  637.  
  638.  
  639. void RefreshScreen()
  640. {
  641.     ReDrawFlag &= ~(RFTransZ|RFPoint);
  642.  
  643.     if( ReDrawFlag )
  644.     {   if( RasWinReady )
  645.         {   RasWinReady = False;
  646.             AdviseUpdate( -4 );
  647.         }
  648.         
  649.         if( ReDrawFlag & RFReSize )
  650.             ReSizeScreen();
  651.  
  652.         if( ReDrawFlag & RFColour )
  653.         {   ClearImage();
  654.             DefineColourMap();
  655.         }
  656.  
  657.         if( Database )
  658.         {   BeginWait();
  659.             if( ReDrawFlag & RFApply ) 
  660.                 ApplyTransform();
  661.             DrawFrame();
  662.             TransferImage();
  663.             EndWait();
  664.         } else
  665.         {   ClearBuffers();
  666.             TransferImage();
  667.         }
  668.         ReDrawFlag = 0;
  669.     }
  670. }
  671.  
  672.  
  673. long FAR PASCAL DDECallB(hWin,uMsg,wArg,lArg)
  674.     HWND hWin; UINT uMsg; WPARAM wArg; LPARAM lArg;
  675. {
  676.     DDEADVISE FAR *options;
  677.     HWND hDest;
  678.  
  679.     register char __huge *cmnd;
  680.     register DDEConv *ptr;
  681.     register int item, done;
  682.     register int i;
  683.     
  684.     done = False;
  685.  
  686.     switch( uMsg )
  687.     {   case( WM_TIMER ):    
  688.                     /* Simulate DDE NAck */
  689.                     lArg = 0L;  
  690.         case( WM_DDE_ACK ):
  691.                     KillTimer( hWin, wArg );
  692.                     if( !(LOWORD(lArg)&0x8000) )
  693.                     {   item = GetItemNumber( HIWORD(lArg) );
  694.                         for( i=0; i<MaxAdviseNum; i++ )
  695.                             if( (AdviseData[i].server==hWin) &&
  696.                                 (AdviseData[i].item==(Byte)item) &&
  697.                                  AdviseData[i].wait )
  698.                             {   GlobalDeleteAtom(AdviseData[i].atom);
  699.                                 GlobalFree(AdviseData[i].data);
  700.                                 AdviseData[i].wait = False;
  701.                                 break;
  702.                             }
  703.                     }
  704.  
  705.                     if( HIWORD(lArg) )
  706.                         GlobalDeleteAtom( HIWORD(lArg) );
  707.                     return( NULL );
  708.  
  709.         case( WM_DDE_REQUEST ):
  710.                     item = GetItemNumber( HIWORD(lArg) );
  711.                     if( item && (LOWORD(lArg)==CF_TEXT) )
  712.                     {   SendItemData( hWin, wArg, ColdLink, item, 0 );
  713.                         GlobalDeleteAtom( HIWORD(lArg) );
  714.                         return( NULL );
  715.                     } 
  716.                     break;
  717.  
  718.         case( WM_DDE_UNADVISE ):
  719.                     if( HIWORD(lArg) )
  720.                     {   item = GetItemNumber( HIWORD(lArg) );
  721.                         if( !item ) break;
  722.                     } else item = 0;
  723.  
  724.                     for( i=0; i<MaxAdviseNum; i++ )
  725.                         if( (AdviseData[i].server==hWin) &&
  726.                             ( !item || AdviseData[i].item==(Byte)item ) )
  727.                         {   if( AdviseData[i].wait )
  728.                             {   GlobalDeleteAtom(AdviseData[i].atom);
  729.                                 GlobalFree(AdviseData[i].data);
  730.                             }
  731.                             AdviseData[i].server = NULL;
  732.                             AdviseCount--;
  733.                             done = True;
  734.                         }
  735.             break;
  736.  
  737.         case( WM_DDE_ADVISE ):
  738.             item = GetItemNumber( HIWORD(lArg) );
  739.                     if( !item || (AdviseCount==MaxAdviseNum ) )
  740.                         break;
  741.  
  742.                     /* Check for established link! */
  743.                     for( i=0; i<MaxAdviseNum; i++ )
  744.                         if( (AdviseData[i].server==hWin) &&
  745.                             (AdviseData[i].item==(Byte)item) ) break;
  746.                     if( i<MaxAdviseNum ) break;
  747.  
  748.                     options = (DDEADVISE FAR*)GlobalLock(LOWORD(lArg));
  749.                     if( !options || options->cfFormat != CF_TEXT ) 
  750.                         break;
  751.  
  752.             for( i=0; i<MaxConvNum; i++ )
  753.                         if( ConvData[i].server==hWin )
  754.                         {   hDest = ConvData[i].client;
  755.                             break;
  756.                         }
  757.  
  758.                     for( i=0; i<MaxAdviseNum; i++ )
  759.                         if( !AdviseData[i].server )
  760.                             break;
  761.  
  762.                     AdviseData[i].server = hWin;
  763.                     AdviseData[i].client = hDest;
  764.                     AdviseData[i].atom = HIWORD(lArg);
  765.                     AdviseData[i].wait = False;
  766.             AdviseData[i].item = item;
  767.                     AdviseCount++;
  768.  
  769.                     if( options->fDeferUpd )
  770.                     {      AdviseData[i].mode = WarmLink;
  771.                     } else if( options->fAckReq )
  772.                     {      AdviseData[i].mode = AckLink;
  773.                     } else AdviseData[i].mode = HotLink;
  774.  
  775.                     PostMessage( wArg, WM_DDE_ACK, hWin,
  776.                                  MAKELONG(0x8000,HIWORD(lArg)) ); 
  777.                     /* SendItemData(hWin,hDest,AdviseData[i].mode,item,i); */
  778.                     GlobalUnlock(LOWORD(lArg));
  779.                     return( NULL );
  780.  
  781.         case( WM_DDE_EXECUTE ):  
  782.                     if( cmnd=(char __huge*)GlobalLock((HANDLE)HIWORD(lArg)) )
  783.                     {   done = ExecuteIPCCommand( cmnd );
  784.                         GlobalUnlock((HANDLE)HIWORD(lArg));
  785.  
  786.                         if( ReDrawFlag ) 
  787.                             RefreshScreen();
  788.                         if( !CommandActive ) 
  789.                             ResetCommandLine(0);
  790.                     }
  791.                     break;
  792.  
  793.                     
  794.         case( WM_DDE_TERMINATE ):
  795.                     /* Destroy all Hot/Warm Links */
  796.                     for( i=0; i<MaxAdviseNum; i++ )
  797.                         if( AdviseData[i].server == hWin )
  798.                         {   AdviseData[i].server = NULL;
  799.                             if( AdviseData[i].wait )
  800.                             {   GlobalDeleteAtom(AdviseData[i].atom);
  801.                                 GlobalFree(AdviseData[i].data);
  802.                             }
  803.                             AdviseCount--;
  804.                         }
  805.  
  806.                     /* Remove the Conversation */
  807.                     for( i=0; i<MaxConvNum; i++ )
  808.                         if( ConvData[i].server == hWin )
  809.                         {   ptr = ConvData+i;
  810.                             if( !ptr->closed )
  811.                                 PostMessage( ptr->client, WM_DDE_TERMINATE,
  812.                                              ptr->server, 0L );
  813.                             DestroyWindow( ptr->server );
  814.                             ptr->server = NULL;
  815.                             ConvCount--;
  816.                             break;
  817.                         }
  818.                     return( NULL );
  819.                     
  820.         default:  return( DefWindowProc(hWin,uMsg,wArg,lArg) );
  821.     }
  822.  
  823.     /* Return a DDE acknowledgement */
  824.     PostMessage( wArg, WM_DDE_ACK, hWin,
  825.                  MAKELONG( (done?0x8000:0), HIWORD(lArg)) ); 
  826.     return( NULL );
  827. }
  828.  
  829.  
  830.  
  831. long FAR PASCAL CmndCallB(hWin,uMsg,wArg,lArg)
  832.     HWND hWin; UINT uMsg; WPARAM wArg; LPARAM lArg;
  833. {
  834.     switch(uMsg)
  835.     {    case(WM_SYSCHAR):    if( lArg & (1L<<29) )  /* ALT-key pressed? */
  836.                                   return(DefWindowProc(hWin,uMsg,wArg,lArg));
  837.  
  838.          case(WM_CHAR):       if( ProcessCharacter(LOBYTE(wArg)) )
  839.                                   if( ExecuteCommand() )
  840.                                       RasMolExit();
  841.                               break;
  842.  
  843.          case(WM_PAINT):      PaintScreen();
  844.                               return(NULL);
  845.                               
  846.         case(WM_SYSKEYDOWN):
  847.         case(WM_KEYDOWN):     switch(LOBYTE(wArg))
  848.                               {   case(0x23): ProcessCharacter(0x05); break;
  849.                                   case(0x24): ProcessCharacter(0x01); break;
  850.                                   case(0x25): ProcessCharacter(0x02); break;
  851.                                   case(0x26): ProcessCharacter(0x10); break;
  852.                                   case(0x27): ProcessCharacter(0x06); break;
  853.                                   case(0x28): ProcessCharacter(0x0e); break;
  854.                                   case(0x2e): ProcessCharacter(0x04); break;
  855.                                   
  856.                                   default:
  857.                                      return(DefWindowProc(hWin,uMsg,wArg,lArg));
  858.                               }
  859.                               break;
  860.         
  861.          case(WM_SETFOCUS):   if( !TermCursor )
  862.                               {   TermCursor = True;
  863.                                   CreateCaret(hWin,NULL,CharWide,CharHigh);
  864.                                   ShowCaret(hWin);
  865.                               }
  866.                               SetCaretPos(TermXPos*CharWide,
  867.                                           TermYPos*CharHigh);
  868.                               return(NULL);
  869.                               
  870.          case(WM_KILLFOCUS):  if( TermCursor )
  871.                               {   TermCursor=False;
  872.                                   HideCaret(hWin);
  873.                                   DestroyCaret();
  874.                               }
  875.                               return(NULL);
  876.                               
  877.          default:  return( DefWindowProc(hWin,uMsg,wArg,lArg) );
  878.     }
  879.  
  880.     if( ReDrawFlag )
  881.         RefreshScreen();
  882.     if( !CommandActive )
  883.         ResetCommandLine(0);
  884.     return(NULL);
  885. }
  886.  
  887.  
  888.  
  889. static void LoadInputFile( format )
  890.     int format;
  891. {
  892.     register char *ext;
  893.     register int num;
  894.  
  895.     switch( format )
  896.     {   case(FormatPDB):      ext = "PDB";  num = 1;  break;
  897.         case(FormatAlchemy):  ext = "MOL";  num = 2;  break;
  898.         case(FormatXYZ):      ext = "XYZ";  num = 3;  break;
  899.     }
  900.  
  901.     ofn1.nFilterIndex = num;
  902.     ofn1.lpstrDefExt = ext;
  903.     *fnamebuf = '\0';
  904.  
  905.     if( GetOpenFileName(&ofn1) )
  906.     {   switch( ofn1.nFilterIndex )
  907.         {   case(1): FetchFile(FormatPDB,False,fnamebuf);     break;
  908.             case(2): FetchFile(FormatAlchemy,False,fnamebuf); break;
  909.             case(3): FetchFile(FormatXYZ,False,fnamebuf);     break;
  910.         }
  911.  
  912.         if( Database )
  913.         {   ReDrawFlag |= RFRefresh | RFColour;
  914.             if( InfoBondCount < 1 )
  915.             {   EnableBackBone(False,80);
  916.             } else EnableWireFrame(True,0);
  917.             CPKColourAttrib();
  918.         }
  919.     }
  920. }
  921.  
  922.  
  923. static void SaveOutputFile( format )
  924.     int format;
  925. {
  926.     register char *ext;
  927.     register int num;
  928.  
  929.     switch( format )
  930.     {   case(IDM_BMP):   ext="BMP";  num=1;  break;
  931.         case(IDM_GIF):   ext="GIF";  num=2;  break;
  932.         case(IDM_EPSF):  ext="PS";   num=3;  break;
  933.         case(IDM_PPM):   ext="PPM";  num=5;  break;
  934.         case(IDM_RAST):  ext="RAS";  num=7;  break;
  935.     }
  936.  
  937.     ofn2.nFilterIndex = num;
  938.     ofn2.lpstrDefExt = ext;
  939.     *fnamebuf = '\0';
  940.     
  941. /*  Default Filename   
  942.  *  dst = fnamebuf;
  943.  *  for( src="RASWIN."; *src; src++ ) *dst++ = *src;
  944.  *  for( src=ext; *src; src++ ) *dst++ = *src;
  945.  *  *dst++ = '\0';
  946.  */
  947.     
  948.     if( GetSaveFileName(&ofn2) )    
  949.         switch( ofn2.nFilterIndex )
  950.         {   case(1):  WriteBMPFile(fnamebuf);             break;
  951.             case(2):  WriteGIFFile(fnamebuf);             break;
  952.             case(3):  WriteEPSFFile(fnamebuf,True,True);  break;
  953.             case(4):  WriteEPSFFile(fnamebuf,False,True); break;
  954.             case(5):  WritePPMFile(fnamebuf,True);        break;
  955.             case(6):  WritePPMFile(fnamebuf,False);       break;
  956.             case(7):  WriteRastFile(fnamebuf,True);       break;
  957.             case(8):  WriteRastFile(fnamebuf,False);      break;
  958.         }
  959. }
  960.  
  961.     
  962. static BOOL HandleMenu( option )
  963.     WPARAM option;
  964. {
  965.     register FARPROC lpProc;
  966.     register int mask;
  967.     
  968.    
  969.     switch(option)
  970.     {   /* File Menu */
  971.         case(IDM_OPEN):   if( !Database )
  972.                               LoadInputFile(FormatPDB);
  973.                           break;
  974.                           
  975.         case(IDM_INFO):   lpProc = MakeProcInstance(InfoCallB,hInstance);
  976.                           DialogBox(hInstance,"InfoBox",CanvWin,lpProc);
  977.                           FreeProcInstance(lpProc);
  978.                           break;
  979.                           
  980.         case(IDM_CUT):    if( OpenClipboard(CanvWin) )
  981.                           {   EmptyClipboard();
  982.                               SetClipboardData(CF_DIB,NULL);
  983.                               SetClipboardData(CF_PALETTE,NULL);
  984.                               CloseClipboard();
  985.                           }
  986.                           break;
  987.         
  988.         case(IDM_PRINT):  if( !PrintImage() )
  989.                           {   if( CommandActive )
  990.                                   WriteChar('\n');
  991.                               WriteString("Warning: No suitable printer!\n");
  992.                               CommandActive = False;
  993.                           }
  994.                           break;
  995.         
  996.         case(IDM_CLOSE):  ZapDatabase();
  997.                           break;
  998.                           
  999.         case(IDM_EXIT):   DestroyWindow(CmndWin);
  1000.                           DestroyWindow(CanvWin);
  1001.                           break;
  1002.                           
  1003.         case(IDM_ABOUT):  lpProc = MakeProcInstance(AboutCallB,hInstance);
  1004.                           DialogBox(hInstance,"AboutBox",CanvWin,lpProc);
  1005.                           FreeProcInstance(lpProc);
  1006.                           break;
  1007.         
  1008.        
  1009.         /* Display Menu */
  1010.         case(IDM_WIREFRAME):  DisableSpacefill();
  1011.                               EnableWireFrame(True,0);
  1012.                               SetRibbonStatus(False,0);
  1013.                               DisableBackBone();
  1014.                   ReDrawFlag |= RFRefresh;
  1015.                               break;
  1016.  
  1017.         case(IDM_BACKBONE):   DisableSpacefill();
  1018.                               DisableWireFrame();
  1019.                               SetRibbonStatus(False,0);
  1020.                               EnableBackBone(False,80);
  1021.                   ReDrawFlag |= RFRefresh;
  1022.                               break;
  1023.  
  1024.         case(IDM_STICKS):     DisableSpacefill();
  1025.                               EnableWireFrame(False,80);
  1026.                               SetRibbonStatus(False,0);
  1027.                               DisableBackBone();
  1028.                   ReDrawFlag |= RFRefresh;
  1029.                               break;
  1030.  
  1031.         case(IDM_SPHERES):    SetVanWaalRadius();
  1032.                               DisableWireFrame();
  1033.                               SetRibbonStatus(False,0);
  1034.                               DisableBackBone();
  1035.                   ReDrawFlag |= RFRefresh;
  1036.                               break;
  1037.  
  1038.         case(IDM_BALLSTICK):  SetRadiusValue(120);
  1039.                               EnableWireFrame(False,40);
  1040.                               SetRibbonStatus(False,0);
  1041.                               DisableBackBone();
  1042.                   ReDrawFlag |= RFRefresh;
  1043.                               break;
  1044.  
  1045.         case(IDM_RIBBONS):    DisableSpacefill();
  1046.                               DisableWireFrame();
  1047.                               SetRibbonStatus(True,0);
  1048.                               DisableBackBone();
  1049.                               ReDrawFlag |= RFRefresh;
  1050.                               break;
  1051.  
  1052.         /* Colours Menu */
  1053.         case(IDM_MONO):     MonoColourAttrib(255,255,255);
  1054.                 ReDrawFlag |= RFColour;  break;
  1055.         case(IDM_CPK):      CPKColourAttrib();
  1056.                 ReDrawFlag |= RFColour;  break;
  1057.         case(IDM_SHAPELY):  ShapelyColourAttrib();
  1058.                 ReDrawFlag |= RFColour;  break;
  1059.         case(IDM_STRUCT):   StructColourAttrib();
  1060.                             ReDrawFlag |= RFColour;  break;
  1061.         case(IDM_GROUP):    ScaleColourAttrib( GroupAttr );
  1062.                 ReDrawFlag |= RFColour;  break;
  1063.         case(IDM_CHAIN):    ScaleColourAttrib( ChainAttr );
  1064.                 ReDrawFlag |= RFColour;  break;
  1065.         case(IDM_TEMPER):   ScaleColourAttrib( TempAttr );
  1066.                 ReDrawFlag |= RFColour;  break;
  1067.         case(IDM_USER):     UserMaskAttrib(MaskColourFlag);
  1068.                 ReDrawFlag |= RFColour;  break;
  1069.         
  1070.        
  1071.        
  1072.         /* Options Menu */
  1073.         case(IDM_SLAB):      ReDrawFlag |= RFRefresh;
  1074.                              UseSlabPlane = !UseSlabPlane;
  1075.                              if( UseSlabPlane )
  1076.                                  UseShadow = False;
  1077.                              break;
  1078.  
  1079.         case(IDM_HYDROGEN):  mask = NormAtomFlag;
  1080.                              if( HetaGroups )
  1081.                                  mask |= HeteroFlag;
  1082.                              Hydrogens = !Hydrogens;
  1083.                  ReDrawFlag |= RFRefresh;
  1084.  
  1085.                              if( Hydrogens )
  1086.                              {      SelectZone(mask|HydrogenFlag);
  1087.                              } else RestrictZone(mask);
  1088.                              break;
  1089.         
  1090.         case(IDM_HETERO):    mask = NormAtomFlag;
  1091.                              if( Hydrogens )
  1092.                                  mask |= HydrogenFlag;
  1093.                              HetaGroups = !HetaGroups;
  1094.                              ReDrawFlag |= RFRefresh;
  1095.  
  1096.                              if( HetaGroups )
  1097.                              {      SelectZone(mask|HeteroFlag);
  1098.                              } else RestrictZone(mask);
  1099.                              break;
  1100.         
  1101.         case(IDM_SPECULAR):  FakeSpecular = !FakeSpecular;
  1102.                              ReDrawFlag |= RFColour;
  1103.                              break;
  1104.         
  1105.         case(IDM_SHADOW):    ReDrawFlag |= RFRefresh;
  1106.                              UseShadow = !UseShadow;
  1107.                              if( UseShadow )
  1108.                              {   ReviseInvMatrix();
  1109.                                  VoxelsClean = False;
  1110.                                  UseSlabPlane = False;
  1111.                                  ReAllocBuffers();
  1112.                              }
  1113.                              break;
  1114.  
  1115.  
  1116.         /* Save Menu */
  1117.         case(IDM_BMP):   case(IDM_GIF):
  1118.         case(IDM_EPSF):  case(IDM_PPM):
  1119.         case(IDM_RAST):    SaveOutputFile( option ); 
  1120.                            break;
  1121.         
  1122.         default:  return(FALSE);
  1123.     }
  1124.     return(TRUE);
  1125. }    
  1126.  
  1127.  
  1128. static HANDLE RenderClipboard( format )
  1129.     WPARAM format;
  1130. {
  1131.     register BITMAPINFO __far *bitmap;
  1132.     register char __huge *src;
  1133.     register char __huge *dst;
  1134.     register HANDLE result;
  1135.     register long size,len;
  1136.     register int i; 
  1137.    
  1138.     if( format==CF_PALETTE )
  1139.     {   if( ColourMap )
  1140.         {   return( CreatePalette(Palette) );
  1141.         } else return( NULL );
  1142.     }    
  1143.     
  1144.     if( !PixMap || (format!=CF_DIB) )
  1145.         return( NULL );
  1146.  
  1147.     len = (long)XRange*YRange*sizeof(Pixel);
  1148.     size = sizeof(BITMAPINFOHEADER) + 256*sizeof(RGBQUAD);
  1149.     if( !(result=GlobalAlloc(GHND,size+len)) ) return( NULL );
  1150.     
  1151.     bitmap = (BITMAPINFO __far *)GlobalLock(result);
  1152.     bitmap->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  1153.     bitmap->bmiHeader.biWidth = XRange;
  1154.     bitmap->bmiHeader.biHeight = YRange;
  1155.     bitmap->bmiHeader.biPlanes = 1;
  1156.     bitmap->bmiHeader.biBitCount = 8;
  1157.     bitmap->bmiHeader.biCompression = BI_RGB;
  1158.     bitmap->bmiHeader.biSizeImage = len;
  1159.     bitmap->bmiHeader.biXPelsPerMeter = 0;
  1160.     bitmap->bmiHeader.biYPelsPerMeter = 0;
  1161.     bitmap->bmiHeader.biClrImportant = 0;
  1162.     bitmap->bmiHeader.biClrUsed = 0;
  1163.     
  1164.     for( i=0; i<256; i++ )
  1165.     {   bitmap->bmiColors[i].rgbBlue  = BLut[i];
  1166.         bitmap->bmiColors[i].rgbGreen = GLut[i];
  1167.         bitmap->bmiColors[i].rgbRed   = RLut[i];
  1168.     }
  1169.     
  1170.    
  1171.     src = (Pixel __huge*)GlobalLock(FBufHandle);
  1172.     dst = ((Pixel __huge*)bitmap)+size;
  1173.     
  1174.     /* Transfer the frame buffer */
  1175.     while( len-- ) *dst++ = *src++;
  1176.     
  1177.     GlobalUnlock(FBufHandle);
  1178.     GlobalUnlock(result);
  1179.     return( result );    
  1180. }
  1181.  
  1182.  
  1183. static void InitiateServer( hWinCli, lParam )
  1184.     HWND hWinCli;  LONG lParam;
  1185. {
  1186.     HWND hWinServ;
  1187.     ATOM aTopicIn, aTopicOut;
  1188.     ATOM aApplIn, aApplOut;
  1189.     
  1190.     char TopicName[16];
  1191.     char ApplName[16];
  1192.     register int i;
  1193.  
  1194.     if( ConvCount == MaxConvNum )
  1195.         return;
  1196.             
  1197.     if( aApplIn = LOWORD(lParam) )
  1198.     {   GlobalGetAtomName(aApplIn,ApplName,14);
  1199.         if( _stricmp(ApplName,"RasWin") )
  1200.             return;
  1201.     } else return;
  1202.     
  1203.     if( aTopicIn = HIWORD(lParam) )
  1204.     {   GlobalGetAtomName(aTopicIn,TopicName,14);
  1205.         /* Test for Valid Topic */
  1206.         /* if( _stricmp(Topic,"System") &&
  1207.          *     _stricmp(Topic,"RemoteControl") )
  1208.          * return;
  1209.          */
  1210.     } else *TopicName = '\0';
  1211.     
  1212.    
  1213.     hWinServ = CreateWindow("RasDDEClass","RasWinDDE",
  1214.                             WS_CHILD, 0, 0, 0, 0,
  1215.                             CanvWin, NULL, hInstance, NULL );
  1216.     if( !hWinServ ) return;
  1217.          
  1218.     for( i=0; i<MaxConvNum; i++ )
  1219.         if( !ConvData[i].server )
  1220.             break;
  1221.             
  1222.     ConvData[i].server = hWinServ;
  1223.     ConvData[i].client = hWinCli;
  1224.     ConvData[i].closed = False;
  1225.     ConvCount++;       
  1226.           
  1227.          
  1228.     /* Main DDE Server */       
  1229.     aTopicOut = NULL;
  1230.     
  1231.     aApplOut = GlobalAddAtom("RasWin");
  1232.     SendMessage( hWinCli, WM_DDE_ACK, hWinServ,
  1233.                  MAKELONG(aApplOut,aTopicOut) ); 
  1234. }
  1235.  
  1236.  
  1237. static void ClampDial( dial, value )
  1238.     int dial;  Real value;
  1239. {
  1240.     register Real temp;
  1241.  
  1242.     temp = DialValue[dial] + value;
  1243.  
  1244.     if( temp > 1.0 )
  1245.     {   DialValue[dial] = 1.0;
  1246.     } else if( temp < -1.0 )
  1247.     {   DialValue[dial] = -1.0;
  1248.     } else DialValue[dial] = temp;
  1249. }
  1250.  
  1251.  
  1252. static void WrapDial( dial, value )
  1253.     int dial;  Real value;
  1254. {
  1255.     register Real temp;
  1256.  
  1257.     temp = DialValue[dial] + value;
  1258.     while( temp < -1.0 )  temp += 2.0;
  1259.     while( temp > 1.0 )   temp -= 2.0;
  1260.     DialValue[dial] = temp;
  1261. }
  1262.  
  1263.  
  1264. void SetMouseMode( mode )
  1265.     int mode;
  1266. {
  1267.     MouseMode = mode;
  1268. }
  1269.  
  1270.  
  1271. static void MouseMove( status, dx, dy )
  1272.     int status, dx, dy;
  1273. {
  1274.     if( MouseMode == MMRasMol )
  1275.     {   if( status & MK_SHIFT )
  1276.         {   if( status & MK_LBUTTON )
  1277.             {   if( dy ) /* Zoom Vertical */
  1278.                 {   ClampDial( 3, (Real)dy/HRange );
  1279.                     ReDrawFlag |= RFZoom;
  1280.                 }
  1281.             } else if( status & (MK_MBUTTON|MK_RBUTTON) )
  1282.                 if( dx ) /* Z Rotation Horizontal */
  1283.                 {   WrapDial( 2, (Real)-dx/WRange );
  1284.                     ReDrawFlag |= RFRotateZ;
  1285.                 }
  1286.         } else if( status & MK_CONTROL )
  1287.         {   if( status & MK_LBUTTON )
  1288.             {   if( dy ) /* Slab Vertical */
  1289.                 {   ClampDial( 7, (Real)dy/YRange );
  1290.                     ReDrawFlag |= RFSlab;
  1291.                 }
  1292.             }
  1293.  
  1294.         } else /* Unmodified! */
  1295.             if( status & MK_LBUTTON )
  1296.             {   if( dx ) /* Rotate Y Horizontal */
  1297.                 {   WrapDial( 1, (Real)dx/WRange );
  1298.                     ReDrawFlag |= RFRotateY;
  1299.                 }
  1300.  
  1301.                 if( dy ) /* Rotate X Vertical */
  1302.                 {   WrapDial( 0, (Real)-dy/HRange );
  1303.                     ReDrawFlag |= RFRotateX;
  1304.                 }
  1305.                 UpdateScrollBars();
  1306.             } else if( status & (MK_MBUTTON|MK_RBUTTON) )
  1307.             {   if( dx ) /* Translate X Horizontal */
  1308.                 {   ClampDial( 4, (Real)dx/XRange );
  1309.                     ReDrawFlag |= RFTransX;
  1310.                 }
  1311.  
  1312.                 if( dy ) /* Translate Y Vertical */
  1313.                 {   ClampDial( 5, (Real)-dy/YRange );
  1314.                     ReDrawFlag |= RFTransY;
  1315.                 }
  1316.             }
  1317.     } else if( MouseMode == MMQuanta )
  1318.     {   if( status & MK_SHIFT )
  1319.         {   if( status & MK_LBUTTON )
  1320.             {   if( dy ) /* Slab Vertical */
  1321.                 {   ClampDial( 7, (Real)dy/YRange );
  1322.                     ReDrawFlag |= RFSlab;
  1323.                 }
  1324.             } else if( status & (MK_MBUTTON|MK_RBUTTON) )
  1325.             {   if( dx ) /* Translate X Horizontal */
  1326.                 {   ClampDial( 4, (Real)dx/XRange );
  1327.                     ReDrawFlag |= RFTransX;
  1328.                 }
  1329.  
  1330.                 if( dy ) /* Translate Y Vertical */
  1331.                 {   ClampDial( 5, (Real)-dy/YRange );
  1332.                     ReDrawFlag |= RFTransY;
  1333.                 }
  1334.             } else /* No Mouse Buttons */
  1335.                 if( dy ) /* Zoom Vertical */
  1336.                 {   ClampDial( 3, (Real)dy/HRange );
  1337.                     ReDrawFlag |= RFZoom;
  1338.                 }
  1339.         } else if( status & (MK_LBUTTON|MK_MBUTTON) )
  1340.         {   if( dx ) /* Rotate Y Horizontal */
  1341.             {   WrapDial( 1, (Real)dx/WRange );
  1342.                 ReDrawFlag |= RFRotateY;
  1343.             }
  1344.  
  1345.             if( dy ) /* Rotate X Vertical */
  1346.             {   WrapDial( 0, (Real)-dy/HRange );
  1347.                 ReDrawFlag |= RFRotateX;
  1348.             }
  1349.             UpdateScrollBars();
  1350.         } else if( status & MK_RBUTTON )
  1351.             if( dx ) /* Z Rotation Horizontal */
  1352.             {   WrapDial( 2, (Real)-dx/WRange );
  1353.                 ReDrawFlag |= RFRotateZ;
  1354.             }
  1355.         
  1356.     } else /* MMInsight */
  1357.         switch( status & (MK_LBUTTON|MK_MBUTTON|MK_RBUTTON) )
  1358.         {   case( MK_LBUTTON ):
  1359.                     if( dx ) /* Rotate Y Horizontal */
  1360.                     {   WrapDial( 1, (Real)dx/WRange );
  1361.                         ReDrawFlag |= RFRotateY;
  1362.                     }
  1363.  
  1364.                     if( dy ) /* Rotate X Vertical */
  1365.                     {   WrapDial( 0, (Real)dy/HRange );
  1366.                         ReDrawFlag |= RFRotateX;
  1367.                     }
  1368.                     break;
  1369.  
  1370.             case( MK_MBUTTON ):
  1371.                     if( dx ) /* Translate X Horizontal */
  1372.                     {   ClampDial( 4, (Real)dx/XRange );
  1373.                         ReDrawFlag |= RFTransX;
  1374.                     }
  1375.  
  1376.                     if( dy ) /* Translate Y Vertical */
  1377.                     {   ClampDial( 5, (Real)dy/YRange );
  1378.                         ReDrawFlag |= RFTransY;
  1379.                     }
  1380.                     break;
  1381.  
  1382.             case( MK_LBUTTON|MK_MBUTTON ):
  1383.                     ClampDial( 3, (Real)dx/WRange - (Real)dy/HRange );
  1384.                     ReDrawFlag |= RFZoom;
  1385.                     break;
  1386.  
  1387.             case( MK_LBUTTON|MK_RBUTTON ):
  1388.                     WrapDial( 2, (Real)dx/WRange - (Real)dy/HRange );
  1389.                     ReDrawFlag |= RFRotateZ;
  1390.                     break;
  1391.  
  1392.             case( MK_LBUTTON|MK_MBUTTON|MK_RBUTTON ):
  1393.                     ClampDial( 7, (Real)dx/XRange - (Real)dy/YRange );
  1394.                     ReDrawFlag |= RFSlab;
  1395.                     break;
  1396.         }
  1397. }
  1398.  
  1399.  
  1400. long FAR PASCAL MainCallB(hWin,uMsg,wArg,lArg)
  1401.     HWND hWin; UINT uMsg; WPARAM wArg; LPARAM lArg;
  1402. {
  1403.     register int pos,status;
  1404.     register int dx, dy;
  1405.     
  1406.     register HPALETTE hCMap;
  1407.     register HANDLE hand;
  1408.     register HMENU hMenu;
  1409.     register HDC hMemDC;
  1410.     register HDC hDC;
  1411.  
  1412.     PAINTSTRUCT ps;
  1413.     RECT rc;
  1414.     
  1415.  
  1416.     CanvWin = hWin;
  1417.     
  1418.     switch(uMsg)
  1419.     {    case(WM_DESTROY):     /* Destroy RasWin */
  1420.                               PostQuitMessage(0);
  1421.                               break;
  1422.  
  1423.         case(WM_ACTIVATE):    if( !wArg ) break;
  1424.         case(WM_QUERYNEWPALETTE):
  1425.                               if( PixMap )
  1426.                               {   hDC = GetDC(hWin);
  1427.                                   hCMap = SelectPalette(hDC,ColourMap,False);
  1428.                                   status = RealizePalette(hDC);
  1429.                                   SelectPalette(hDC,hCMap,False);
  1430.                                   ReleaseDC(hWin,hDC);
  1431.                                   
  1432.                                   if( status )
  1433.                                   {   InvalidateRect(hWin,NULL,True);
  1434.                                       return True;
  1435.                                   }
  1436.                               }
  1437.                               return(NULL);
  1438.                               
  1439.         case(WM_PALETTECHANGED):
  1440.                               if( PixMap && (wArg!=hWin) )
  1441.                               {   hDC = GetDC(hWin);
  1442.                                   hCMap = SelectPalette(hDC,ColourMap,False);
  1443.                                   if( RealizePalette(hDC) )
  1444.                                       InvalidateRect(hWin,NULL,True);
  1445.                                   SelectPalette(hDC,hCMap,False);
  1446.                                   ReleaseDC(hWin,hDC);
  1447.                               }
  1448.                               return(NULL);
  1449.                               
  1450.                              
  1451.         case(WM_INITMENUPOPUP):  /* Initialise Checks */
  1452.                               if( lArg == 3 )
  1453.                               {   /* Options Menu */
  1454.                                   hMenu = (HMENU)wArg;
  1455.  
  1456.                                   status = UseSlabPlane ? MF_CHECKED 
  1457.                                                         : MF_UNCHECKED;
  1458.                                   CheckMenuItem(hMenu,IDM_SLAB,status);
  1459.  
  1460.                                   status = Hydrogens ? MF_CHECKED 
  1461.                                                      : MF_UNCHECKED;
  1462.                                   CheckMenuItem(hMenu,IDM_HYDROGEN,status);
  1463.  
  1464.                                   status = HetaGroups ? MF_CHECKED 
  1465.                                                       : MF_UNCHECKED;
  1466.                                   CheckMenuItem(hMenu,IDM_HETERO,status);
  1467.  
  1468.                                   status = FakeSpecular ? MF_CHECKED 
  1469.                                                         : MF_UNCHECKED;
  1470.                                   CheckMenuItem(hMenu,IDM_SPECULAR,status);
  1471.  
  1472.                                   status = UseShadow ? MF_CHECKED 
  1473.                                                      : MF_UNCHECKED;
  1474.                                   CheckMenuItem(hMenu,IDM_SHADOW,status);
  1475.                               }
  1476.                               return( NULL );                      
  1477.  
  1478.         case(WM_SIZE):        GetClientRect(hWin,&rc);
  1479.                               YRange = rc.bottom;
  1480.                   XRange = rc.right;
  1481.                   
  1482.                   /* Ensure Long Aligned */
  1483.                   XRange -= (XRange%4);
  1484.                   
  1485.                   Range = MinFun(XRange,YRange);
  1486.                   ReDrawFlag |= RFReSize;
  1487.                   HRange = YRange>>1;
  1488.                   WRange = XRange>>1;
  1489.                               ClearImage();
  1490.                               break;
  1491.  
  1492.         case(WM_HSCROLL):     /* Horizontal Scroll */
  1493.                   pos = GetScrollPos(hWin,SB_HORZ);
  1494.                   switch( wArg )
  1495.                   {   case(SB_LINEDOWN):  pos += 5;   break;
  1496.                       case(SB_PAGEDOWN):  pos += 10;  break;
  1497.                       case(SB_PAGEUP):    pos -= 10;  break;
  1498.                       case(SB_LINEUP):    pos -= 5;   break;
  1499.                                   default:            return(NULL);
  1500.  
  1501.                       case(SB_THUMBPOSITION):
  1502.                       case(SB_THUMBTRACK):
  1503.                                  pos = LOWORD(lArg);
  1504.                                  break;
  1505.                   }
  1506.                   
  1507.                   if( pos>100 ) 
  1508.                   {   pos -= 100;
  1509.                   } else if( pos<0 ) 
  1510.                       pos += 100; 
  1511.                  
  1512.                   SetScrollPos(hWin,SB_HORZ,pos,TRUE);
  1513.                   DialValue[1] = (pos/50.0)-1.0;
  1514.                   ReDrawFlag |= RFRotateY;
  1515.                               break;                      
  1516.  
  1517.         case(WM_VSCROLL):     /* Vertical Scroll */
  1518.                   pos = GetScrollPos(hWin,SB_VERT);
  1519.                   switch( wArg )
  1520.                   {   case(SB_LINEDOWN):  pos += 5;   break;
  1521.                       case(SB_PAGEDOWN):  pos += 10;  break;
  1522.                       case(SB_PAGEUP):    pos -= 10;  break;
  1523.                       case(SB_LINEUP):    pos -= 5;   break;
  1524.                                   default:            return(NULL);
  1525.  
  1526.                       case(SB_THUMBPOSITION):
  1527.                       case(SB_THUMBTRACK):
  1528.                                  pos = LOWORD(lArg);
  1529.                                  break;
  1530.                   }
  1531.                   
  1532.                   if( pos>100 ) 
  1533.                   {   pos -= 100;
  1534.                   } else if( pos<0 ) 
  1535.                       pos += 100; 
  1536.                  
  1537.                   SetScrollPos(hWin,SB_VERT,pos,TRUE);
  1538.                   DialValue[0] = 1.0-(pos/50.0);
  1539.                   ReDrawFlag |= RFRotateX;
  1540.                               break;                      
  1541.  
  1542.         case(WM_LBUTTONDOWN): 
  1543.         case(WM_MBUTTONDOWN):
  1544.         case(WM_RBUTTONDOWN): InitX = PointX = LOWORD(lArg);
  1545.                               InitY = PointY = HIWORD(lArg);
  1546.                               HeldButton = True;
  1547.                               SetCapture(hWin);
  1548.                               break;
  1549.         
  1550.         case(WM_LBUTTONUP):
  1551.         case(WM_MBUTTONUP):
  1552.         case(WM_RBUTTONUP): /* Mouse Buttons */
  1553.                               HeldButton = False;
  1554.                               ReleaseCapture();
  1555.  
  1556.                               if( Database )
  1557.                               {   PointX = LOWORD(lArg);
  1558.                                   PointY = HIWORD(lArg);
  1559.                                   if( IsClose(PointX,InitX) &&
  1560.                                       IsClose(PointY,InitY) )
  1561.                                   {   IdentifyAtom(PointX,YRange-PointY);
  1562.                       AdviseUpdate(AdvPickNumber);
  1563.                       AdviseUpdate(AdvPickAtom);
  1564.                   }
  1565.                               }
  1566.                               break;
  1567.  
  1568.  
  1569.         case(WM_MOUSEMOVE):   /* Mouse Movement */
  1570.                               if( !HeldButton )
  1571.                               {   if( (MouseMode==MMQuanta) &&
  1572.                                       (wArg & MK_SHIFT) )
  1573.                                   {   InitX = PointX = LOWORD(lArg);
  1574.                                       InitY = PointY = HIWORD(lArg);
  1575.                                       HeldButton = True;
  1576.                                       SetCapture(hWin);
  1577.                                   }
  1578.                                   break;
  1579.                               }
  1580.  
  1581.                               if( IsClose((int)LOWORD(lArg),InitX) &&
  1582.                                   IsClose((int)HIWORD(lArg),InitY) )
  1583.                                   break;
  1584.  
  1585.                               if( wArg & (MK_LBUTTON|MK_MBUTTON|
  1586.                                           MK_RBUTTON|MK_SHIFT) )
  1587.                               {   dx = (int)LOWORD(lArg)-PointX;
  1588.                                   dy = (int)HIWORD(lArg)-PointY;
  1589.                                   MouseMove( wArg, dx, dy );
  1590.                                   PointX = LOWORD(lArg);
  1591.                                   PointY = HIWORD(lArg);
  1592.                               } else  /* No Buttons! */
  1593.                               {   HeldButton = False;
  1594.                                   ReleaseCapture();
  1595.                               }
  1596.                               break;
  1597.  
  1598.                                       
  1599.         case(WM_SETFOCUS):    /* Obtain Window Focus */ 
  1600.         case(WM_KILLFOCUS):   /* Release Window Focus */
  1601.                               SendMessage(CmndWin,uMsg,wArg,lArg);     
  1602.                               return( NULL );
  1603.         
  1604.         case(WM_PAINT):       hDC = BeginPaint(hWin,&ps);
  1605.                               SetBkMode(hDC,TRANSPARENT);
  1606.                               if( PixMap )
  1607.                               {   SetWindowOrg(hDC,0,0);
  1608.                                   hCMap = SelectPalette(hDC,ColourMap,False);
  1609.                                   RealizePalette(hDC);
  1610.                                   
  1611.                                   hMemDC = CreateCompatibleDC(hDC);
  1612.                                   SelectObject(hMemDC,PixMap);
  1613.                                   BitBlt(hDC,0,0,XRange,YRange,
  1614.                                          hMemDC,0,0,SRCCOPY);
  1615.                                          
  1616.                                   SelectPalette(hDC,hCMap,False);      
  1617.                                   DeleteDC(hMemDC);
  1618.                               } else /* Erase Update Region */
  1619.                               {    GetUpdateRect(hWin,&rc,False);
  1620.                                    FillRect( hDC, &rc,
  1621.                                       GetStockObject(BLACK_BRUSH) );
  1622.                               }
  1623.                               EndPaint(hWin,&ps);
  1624.                               if( !RasWinReady )
  1625.                               {   RasWinReady = True;
  1626.                                   AdviseUpdate(-4);
  1627.                               }
  1628.                               return( NULL );
  1629.         
  1630.         case(WM_SYSCHAR):     if( lArg & (1L<<29) )  /* ALT-key pressed? */
  1631.                                   return(DefWindowProc(hWin,uMsg,wArg,lArg));
  1632.         case(WM_CHAR):        if( ProcessCharacter(LOBYTE(wArg)) )
  1633.                                   if( ExecuteCommand() )
  1634.                                       RasMolExit();
  1635.                               break;
  1636.  
  1637.         case(WM_SYSKEYDOWN):
  1638.         case(WM_KEYDOWN):     switch(LOBYTE(wArg))
  1639.                               {   case(0x23): ProcessCharacter(0x05); break;
  1640.                                   case(0x24): ProcessCharacter(0x01); break;
  1641.                                   case(0x25): ProcessCharacter(0x02); break;
  1642.                                   case(0x26): ProcessCharacter(0x10); break;
  1643.                                   case(0x27): ProcessCharacter(0x06); break;
  1644.                                   case(0x28): ProcessCharacter(0x0e); break;
  1645.                                   case(0x2e): ProcessCharacter(0x04); break;
  1646.                                   
  1647.                                   default:
  1648.                                      return(DefWindowProc(hWin,uMsg,wArg,lArg));
  1649.                               }
  1650.                               break;
  1651.  
  1652.         case(WM_RENDERALLFORMATS):
  1653.                               OpenClipboard(hWin);
  1654.                               SendMessage(hWin,WM_RENDERFORMAT,CF_DIB,0L);
  1655.                               SendMessage(hWin,WM_RENDERFORMAT,CF_PALETTE,0L);
  1656.                               CloseClipboard();
  1657.                               return( NULL );
  1658.                               
  1659.         case(WM_RENDERFORMAT):
  1660.                               if( hand = RenderClipboard(wArg) )
  1661.                                   SetClipboardData(wArg,hand);
  1662.                               return( NULL );
  1663.                               
  1664.  
  1665.         case(WM_DDE_INITIATE): /* DDE Server Connection */
  1666.                               InitiateServer((HWND)wArg,lArg);
  1667.                               return( NULL );
  1668.                                               
  1669.         case(WM_COMMAND):     if( HandleMenu(wArg) )
  1670.                                   break;
  1671.                               
  1672.            default:              return( DefWindowProc(hWin,uMsg,wArg,lArg) );
  1673.  
  1674.     }
  1675.  
  1676.         
  1677.     if( ReDrawFlag )
  1678.         RefreshScreen();
  1679.     if( !CommandActive )
  1680.         ResetCommandLine(0);
  1681.         
  1682.     return(NULL);
  1683. }
  1684.  
  1685.  
  1686. static int InitialiseApplication()
  1687. {
  1688.     WNDCLASS wc;
  1689.     
  1690.     InstanceNo = 0;
  1691.  
  1692.     wc.style = NULL;
  1693.     wc.hIcon = LoadIcon(hInstance,"RasWinIcon");
  1694.     wc.hInstance = hInstance;
  1695.     wc.cbWndExtra = 0;
  1696.     wc.cbClsExtra= 0;
  1697.     
  1698.     /* Canvas Window Class */
  1699.     wc.lpfnWndProc = MainCallB;
  1700.     wc.hbrBackground = GetStockObject(BLACK_BRUSH);
  1701.     wc.hCursor = LoadCursor(hInstance,"RasWinCursor");
  1702.     wc.lpszClassName = "RasWinClass";
  1703.     wc.lpszMenuName = "RasWinMenu";
  1704.  
  1705.     if( !RegisterClass(&wc) )
  1706.         return( NULL );
  1707.         
  1708.     /* Terminal Window Class */
  1709.     wc.lpfnWndProc = CmndCallB;
  1710.     wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
  1711.     wc.hCursor = LoadCursor(NULL,IDC_ARROW);
  1712.     wc.lpszClassName = "RasCliClass";
  1713.     wc.lpszMenuName = NULL;
  1714.  
  1715.     if( !RegisterClass(&wc) )
  1716.         return( NULL );
  1717.         
  1718.     /* DDE Server Window Class */
  1719.     wc.lpfnWndProc = DDECallB;
  1720.     wc.lpszClassName = "RasDDEClass";
  1721.     wc.hbrBackground = NULL;
  1722.     wc.hCursor = NULL;
  1723.     wc.hIcon = NULL;
  1724.         
  1725.     return( RegisterClass(&wc) );
  1726. }
  1727.  
  1728.  
  1729. static char *RegisterFormat( buffer, desc, ext )
  1730.     char *buffer, *desc, *ext;
  1731. {
  1732.     while( *buffer++ = *desc++ );
  1733.     while( *buffer++ = *ext++ );
  1734.     return( buffer );
  1735. }
  1736.  
  1737.     
  1738. int PASCAL WinMain(hCurrent,hPrevious,lpCmdLine,nCmdShow)
  1739.     HANDLE hCurrent,hPrevious;
  1740.     LPSTR lpCmdLine;
  1741.     int nCmdShow;
  1742. {
  1743.     register char *dst;
  1744.     register char *ptr;
  1745.     register int i;
  1746.     MSG event;
  1747.  
  1748.  
  1749.     hInstance = hCurrent;
  1750.     if( hPrevious )
  1751.     {   GetInstanceData(hPrevious,(BYTE*)&InstanceNo,sizeof(int));
  1752.         InstanceNo++;
  1753.     } else if( !InitialiseApplication() )
  1754.         return(NULL);
  1755.  
  1756.    
  1757.     dst = ifilters;
  1758.     dst = RegisterFormat(dst,"Brookhaven Databank","*.PDB;*.ENT");
  1759.     dst = RegisterFormat(dst,"Alchemy File Format","*.MOL");
  1760.     /* dst = RegisterFormat(dst,"MSC (XMol) XYZ Format","*.XYZ"); */
  1761.     *dst = '\0';
  1762.  
  1763.     /* Load File Common Dialog Box */
  1764.     ofn1.lStructSize=sizeof(OPENFILENAME);
  1765.     ofn1.Flags = OFN_NOCHANGEDIR | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
  1766.     ofn1.lpstrFilter = ifilters;
  1767.     ofn1.lpstrTitle = "Select Molecular Coordinate File";
  1768.     ofn1.lpstrFile = fnamebuf;
  1769.     ofn1.nMaxFile = 128;
  1770.  
  1771.     ofn1.lpstrCustomFilter = NULL;
  1772.     ofn1.lpstrInitialDir = NULL;
  1773.     ofn1.lpstrFileTitle = NULL;
  1774.     ofn1.hwndOwner = NULL;
  1775.                         
  1776.     
  1777.     dst = ofilters;
  1778.     dst = RegisterFormat(dst,"Microsoft Bitmap","*.BMP");
  1779.     dst = RegisterFormat(dst,"CompuServe GIF","*.GIF");
  1780.     dst = RegisterFormat(dst,"Colour PostScript","*.PS;*.EPS");
  1781.     dst = RegisterFormat(dst,"Mono PostScript","*.PS;*.EPS");
  1782.     dst = RegisterFormat(dst,"Raw Portable Pixmap","*.PPM");
  1783.     dst = RegisterFormat(dst,"ASCII Portable Pixmap","*.PPM");
  1784.     dst = RegisterFormat(dst,"RLE Sun Rasterfile","*.RAS;*.IM8");
  1785.     dst = RegisterFormat(dst,"Sun Rasterfile","*.RAS");
  1786.     *dst = '\0';
  1787.     
  1788.    
  1789.     /* Save File Common Dialog Box */
  1790.     ofn2.lStructSize=sizeof(OPENFILENAME);
  1791.     ofn2.Flags = OFN_NOCHANGEDIR | OFN_HIDEREADONLY | OFN_NOREADONLYRETURN
  1792.                | OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST;
  1793.     ofn2.lpstrFilter = ofilters;
  1794.     ofn2.lpstrTitle = "Select Graphics Ouptut File";
  1795.     ofn2.lpstrFile = fnamebuf;
  1796.     ofn2.nMaxFile = 128;
  1797.  
  1798.     ofn2.lpstrCustomFilter = NULL;
  1799.     ofn2.lpstrInitialDir = NULL;
  1800.     ofn2.lpstrFileTitle = NULL;
  1801.     ofn2.hwndOwner = NULL;
  1802.  
  1803.  
  1804.     ConvCount = 0;
  1805.     AdviseCount = 0;
  1806.     for( i=0; i<MaxConvNum; i++ )
  1807.         ConvData[i].server = NULL;
  1808.     for( i=0; i<MaxAdviseNum; i++ )
  1809.     AdviseData[i].server = NULL;
  1810.     RasWinReady = True;
  1811.     HeldButton = False;
  1812.  
  1813.     if( !GetProfileString("extensions","pdb","",fnamebuf,128) )
  1814.         WriteProfileString("extensions","pdb","raswin.exe ^.pdb");
  1815.     if( !GetProfileString("extensions","ent","",fnamebuf,128) )
  1816.         WriteProfileString("extensions","ent","raswin.exe ^.ent");
  1817.     DDETimeOut = GetPrivateProfileInt("RasWin","DDETimeOut",
  1818.                                       DefaultTimeOut,"RASWIN.INI"); 
  1819.    
  1820.  
  1821.     FakeSpecular = False; 
  1822.     MouseMode = MMRasMol;
  1823.     SpecPower = 8;
  1824.  
  1825.     ReDrawFlag = 0;
  1826.     Interactive = True;
  1827.     if( !InitTerminal(hInstance) ||
  1828.         !OpenDisplay(hInstance,nCmdShow) )
  1829.        return(NULL);
  1830.  
  1831.     WriteString("RasMol Molecular Renderer\n");
  1832.     WriteString("Roger Sayle, February 1994\n");
  1833.     WriteString("Version 2.3\n\n");
  1834.             
  1835.     InitialiseCommand(); 
  1836.     InitialiseTransform();
  1837.     InitialiseDatabase();
  1838.     InitialiseRenderer();
  1839.     InitialisePixUtils();
  1840.     InitialiseAbstree();
  1841.     InitialiseOutFile();
  1842.     LoadInitFile();
  1843.    
  1844.     ResetCommandLine(1);
  1845.     
  1846.     if( *lpCmdLine )
  1847.     {   ptr = fnamebuf;
  1848.         while( *ptr++ = *lpCmdLine++ );
  1849.         if( FetchFile(FormatPDB,True,fnamebuf) )
  1850.         {   ReDrawFlag |= RFRefresh | RFColour;
  1851.             if( InfoBondCount < 1 )
  1852.             {   EnableBackBone(False,80);
  1853.             } else EnableWireFrame(True,0);
  1854.             CPKColourAttrib();
  1855.             RefreshScreen();
  1856.         }   
  1857.     }
  1858.    
  1859.     while( GetMessage(&event,NULL,0,0) )
  1860.     {   TranslateMessage(&event);
  1861.         DispatchMessage(&event);
  1862.     }
  1863.     DeleteObject(TermFont);
  1864.     CloseDDELinks();
  1865.     CloseDisplay();
  1866.  
  1867.     return( event.wParam );
  1868. }
  1869.  
  1870.